/*
 * Copyright (c) 2009, Jan Pastor. All Rights Reserved.
 */

package sk.jp.jitag.model;

import java.util.List;

import com.db4o.config.annotations.Indexed;

import sk.jp.jitag.dao.db4o.Column;
import sk.jp.jitag.dao.db4o.Unique;
import sk.jp.jitag.dao.db4o.BaseEntity;

/**
 * Representation of <i>media file</i>.
 */
public class File extends BaseEntity {

    public static final int PATH_MAX_LEN = 2048;
    public static final int NAME_MAX_LEN = 512;
    public static final int EXT_MAX_LEN = 64;

    private static final Column _ID = new Column("id");
    private static final Column _HASH = new Column("hash");
    private static final Column _FOR_DELETE = new Column("forDelete");
    private static final Column _PATH = new Column("path");
    private static final Column _NAME = new Column("name");
    private static final Column _EXTENSION = new Column("extension");
    private static final Column _TAGS = new Column("tags");
    private static final Column _RATING = new Column("rating");

    //----------------------------------------------------------------------

    /**
     * File identifier.
     * <p>unique, indexed, notnull, read-only.
     */
    @Indexed
    @Unique
    private Integer id = null;

    /**
     * Content hash.
     * <p>indexed, notnull.
     */
    @Indexed
    private Integer hash = null;

    /**
     * Can be removed from database - phisical file doesn't exists.
     */
    private Boolean forDelete = Boolean.FALSE;

    /**
     * Absolute path of directory where file is placed (without file part!).
     * <p>unique, indexed, notnull, maxlen:{@link #PATH_MAX_LEN}, read-only.
     * <p>(for renaming, create new instance and copy attribs).
     */
    @Indexed
    private String path = null;

    /**
     * Complete file name withOUT(!) extension.
     * <p>indexed, notnull, maxlen:{@link #NAME_MAX_LEN}, read-only.
     * <p>(for renaming, create new instance and copy attribs).
     */
    @Indexed
    private String name = null;

    /**
     * File extension (part of file name after last '.'). 
     * <p>indexed, notnull, maxlen:{@link #EXT_MAX_LEN}, read-only.
     * <p>(for renaming, create new instance and copy attribs).
     */
    @Indexed
    private String extension = null;

    /**
     * Tags associated to this file.
     */
    @Indexed
    private List<Tag> tags = null;

    /**
     * Rating.
     * <P>indexed.
     */
    @Indexed
    private Integer rating = 0;

    //----------------------------------------------------------------------

    /**
     * Safe iunitialization of new entity with initialized non-null (required) fields.
     * @param id
     * @param hash
     * @param path
     * @param name
     * @param extension
     */
    public File(Integer id, Integer hash, String path, String name, String extension) {
        checkNotNull(_ID, id);
        checkNotNull(_HASH, hash);
        checkNotNullNotEmpty(_PATH, path);
        checkMaxLen(_PATH, path, PATH_MAX_LEN);
        checkNotNullNotEmpty(_NAME, name);
        checkMaxLen(_NAME, name, NAME_MAX_LEN);
        checkNotNullNotEmpty(_EXTENSION, extension);
        checkMaxLen(_EXTENSION, extension, EXT_MAX_LEN);

        this.id = id;
        this.hash = hash;
        this.path = path;
        this.name = name;
        this.extension = extension;

        tags = createList();
    }

    //----------------------------------------------------------------------

    public Integer getId() {
        return id;
    }

    public Integer getHash() {
        return hash;
    }

    public File setHash(Integer hash) {
        checkNotNull(_HASH, hash);
        this.hash = hash;
        return this;
    }

    public String getPath() {
        return path;
    }

    public String getName() {
        return name;
    }

    public String getExtension() {
        return extension;
    }

    public File setForDelete(Boolean forDelete) {
        this.forDelete = forDelete;
        return this;
    }

    /**
     * @return if value is null, returns false; never null.
     */
    public Boolean isForDelete() {
        return forDelete != null ? forDelete : Boolean.FALSE;
    }

    public File setRating(Integer rating) {
        this.rating = rating != null ? rating : 0;
        return this;
    }

    /**
     * @return rating value or 0 if not set.
     */
    public Integer getRating() {
        return rating;
    }

    public File setTags(List<Tag> tags) {
        if(tags != null){
            this.tags = createList(tags);
        }else{
            this.tags = createList(0);
        }
        return this;
    }

    public File addTag(Tag tag){
        tags.add(tag);
        return this;
    }

    /**
     * @return if value is null, returns empty list; never null.
     */
    public List<Tag> getTags() {
        return tags;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append("File");
        sb.append("{id=").append(id);
        sb.append(", hash=").append(hash);
        sb.append(", forDelete=").append(forDelete);
        sb.append(", path='").append(path).append('\'');
        sb.append(", name='").append(name).append('\'');
        sb.append(", extension='").append(extension).append('\'');
        sb.append(", tags.size=").append(tags != null ? tags.size() : "null");
        sb.append(", rating=").append(rating);
        sb.append('}');
        return sb.toString();
    }
}
